package io.renren.controller;

import io.renren.annotation.Login;
import io.renren.annotation.LoginUser;
import io.renren.cloud.OSSFactory;
import io.renren.common.exception.RRException;
import io.renren.common.utils.ConfigConstant;
import io.renren.common.utils.EmojiStringUtils;
import io.renren.common.utils.HttpClientUtils;
import io.renren.common.utils.ProjectConstant;
import io.renren.common.utils.R;
import io.renren.common.validator.Assert;
import io.renren.common.validator.ValidatorUtils;
import io.renren.entity.MemberEntity;
import io.renren.entity.RecDownloadEntity;
import io.renren.entity.SysOssEntity;
import io.renren.entity.TokenEntity;
import io.renren.form.LoginForm;
import io.renren.form.PhoneCodeForm;
import io.renren.form.RegisterForm;
import io.renren.service.MemberService;
import io.renren.service.PhoneCodeService;
import io.renren.service.RecDownloadService;
import io.renren.service.SysConfigService;
import io.renren.service.SysOssService;
import io.renren.service.TokenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import springfox.documentation.annotations.ApiIgnore;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;

/**
 * 注册接口
 * 
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2017-03-26 17:27
 */
@RestController
@RequestMapping("/api")
@Api(tags = "登录与注册接口")
public class ApiAppController extends AbstractController {

	@Autowired
	MemberService memberService;

	@Autowired
	PhoneCodeService phoneCodeService;

	@Autowired
	SysConfigService sysConfigService;

	@Autowired
	RecDownloadService recDownloadService;

	@Autowired
	TokenService tokenService;

	@Autowired
	SysOssService sysOssService;

	@PostMapping("downloadapp")
	@ApiOperation("下载APP")
	public R downloadapp(PhoneCodeForm form) {
		// 表单校验
		Assert.hasText(form.getMobile(), "手机号无效");
		if (StringUtils.isNotBlank(form.getRecPerson()) && memberService.selectCount(new EntityWrapper<MemberEntity>().eq("mobile", form.getMobile())) == 0
				&& memberService.selectCount(new EntityWrapper<MemberEntity>().eq("status", ProjectConstant.COMMON_STATUS_ENABLE).eq("code", form.getRecPerson())) == 1) {
			RecDownloadEntity entity = new RecDownloadEntity();
			entity.setMobile(form.getMobile());
			entity.setRecPerson(form.getRecPerson());
			recDownloadService.insertOrUpdate(entity);
		}
		return R.ok();
	}

	@Login
	@PostMapping("bindMobile")
	@ApiOperation("绑定手机")
	public R bindMobile(@ApiIgnore @LoginUser MemberEntity member, @RequestBody PhoneCodeForm form) {
		// 表单校验
		ValidatorUtils.validateEntity(form);
		ApiPhoneCodeController.checkCaptcha(form.getMobile(), form.getCaptcha(), ProjectConstant.PHONECODE_TYPE_BIND);
		memberService.bindMobile(member, form);
		return R.ok();
	}

	@SuppressWarnings("unchecked")
	@PostMapping("login")
	@ApiOperation("登录")
	public R login(@RequestBody LoginForm form) {
		// 表单校验
		ValidatorUtils.validateEntity(form);

		MemberEntity member = null;
		if (StringUtils.isNotBlank(form.getMobile())) {
			Assert.hasText(form.getCaptcha(), "验证码不能为空");
			ApiPhoneCodeController.checkCaptcha(form.getMobile(), form.getCaptcha(), ProjectConstant.PHONECODE_TYPE_LOGIN);
			member = memberService.selectOne(new EntityWrapper<MemberEntity>().eq("mobile", form.getMobile()));
			if (member == null) {
				RegisterForm regForm = new RegisterForm();
				regForm.setMobile(form.getMobile());
				regForm.setNickname("用户" + RandomStringUtils.randomNumeric(4));
				regForm.setHeadImg("../images/default-headImg.jpg");
				memberService.save(regForm);
				member = memberService.selectOne(new EntityWrapper<MemberEntity>().eq("mobile", form.getMobile()));
			} else {
				member.setLastLoginTime(new Date());
				Assert.isTrue(memberService.updateById(member), "系统繁忙");
			}
		} else if (StringUtils.isNotBlank(form.getCode())) {
			String appid = sysConfigService.getValue(ConfigConstant.WX_APPID);
			String result = HttpClientUtils.sendHttpGet(String.format(ConfigConstant.WX_GET_REFRESH_TOKEN, appid, form.getToken()));
			Map<String, String> map = JSON.parseObject(result, Map.class);
			String access_token = map.get("access_token");
			Assert.hasText(access_token, "参数异常");
			String openid = form.getCode();
			Assert.hasText(openid, "参数异常");

			// 获取微信用户信息
			result = HttpClientUtils.sendHttpGet(String.format(ConfigConstant.WX_GET_USERINFO, access_token, openid));
			map = JSON.parseObject(result, Map.class);
			Assert.hasText(map.get("openid"), "参数异常");
			member = memberService.selectOne(new EntityWrapper<MemberEntity>().eq("openid", openid));
			if (member == null) {
				// 注册
				RegisterForm regForm = new RegisterForm();
				regForm.setOpenid(openid);
				try {
					if (StringUtils.isBlank(map.get("headimgurl"))) {
						regForm.setHeadImg("../images/default-headImg.jpg");
					} else {
						regForm.setHeadImg(uploadFile(map.get("headimgurl"), null));// 上传头像
					}
					if (EmojiStringUtils.hasEmoji(map.get("nickname"))) {
						regForm.setNickname(EmojiStringUtils.replaceEmoji(map.get("nickname")));
					} else {
						regForm.setNickname(map.get("nickname"));
					}
				} catch (Exception e) {
					logger.error("headimgurl:" + map.get("headimgurl"));
					logger.error("nickname:" + map.get("nickname"));
				}
				memberService.save(regForm);

				member = memberService.selectOne(new EntityWrapper<MemberEntity>().eq("openid", openid));
			} else {
				try {
					if (StringUtils.isNotBlank(map.get("headimgurl"))) {
						member.setHeadImg(uploadFile(map.get("headimgurl"), member.getHeadImg()));
					}
					if (EmojiStringUtils.hasEmoji(map.get("nickname"))) {
						member.setNickname(EmojiStringUtils.replaceEmoji(map.get("nickname")));
					} else {
						member.setNickname(map.get("nickname"));
					}
				} catch (Exception e) {
					logger.error("headimgurl:" + map.get("headimgurl"));
					logger.error("nickname:" + map.get("nickname"));
				}
				member.setLastLoginTime(new Date());
				Assert.isTrue(memberService.updateById(member), "系统繁忙");
			}
		} else {
			throw new RRException("登录失败");
		}

		// 用户登录
		Map<String, Object> map = memberService.login(member);

		return R.ok(map);
	}

	@Login
	@PostMapping("resetToken")
	@ApiOperation("重置token")
	public R resetToken(@ApiIgnore @LoginUser MemberEntity member) {
		if (member.getStatus() == ProjectConstant.COMMON_STATUS_DISABLE) {
			tokenService.expireToken(member.getId());
			throw new RRException("账号被禁用", 999);
		}
		// 最近登录时间
		member.setLastLoginTime(new Date());
		memberService.updateById(member);

		TokenEntity tokenEntity = tokenService.createToken(member.getId());// 重置token
		Map<String, Object> map = new HashMap<>(2);
		map.put("token", tokenEntity.getToken());
		map.put("expire", tokenEntity.getExpireTime().getTime());
		return R.ok(map);
	}

	@Login
	@PostMapping("logout")
	@ApiOperation("退出")
	public R logout(@ApiIgnore @RequestAttribute("userId") long userId) {
		tokenService.expireToken(userId);
		return R.ok();
	}

	/**
	 * 上传文件
	 * 
	 * @param file
	 * @param type
	 */
	private String uploadFile(String url, String oldUrl) {

		// 上传文件
		try {
			String fileName = DigestUtils.md5Hex(url);
			if (oldUrl != null && oldUrl.indexOf(fileName) != -1) {
				return oldUrl;
			}
			BufferedImage image = ImageIO.read(new URL(url));
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ImageIO.write(image, "JPEG", baos);
			baos.flush();
			byte[] bytes = baos.toByteArray();
			baos.close();
			// 文件路径
			url = OSSFactory.build().upload(bytes, "head/" + fileName + ".jpg");
			// 保存文件信息
			SysOssEntity ossEntity = new SysOssEntity();
			ossEntity.setUrl(url);
			ossEntity.setCreateDate(new Date());
			sysOssService.insert(ossEntity);
			return url;
		} catch (Exception e) {
			logger.error("头像保存失败", e);
			throw new RRException("头像保存失败");
		}
	}
}
